//******************************************************************************
// @File: cyzDetectorConstruction.cc
// @Author: Cyz
// @Date: 2020年 4月30日 星期四 20时11分17秒 CST
// @Description: 
//		构建小人的身体
//		头：球体 直径 180mm
//		脖子：圆柱体 直径 100mm 高 90mm
//		躯干：长方体 长 260mm 宽 120mm 高 500mm
//		腿：圆柱体 直径 110mm 高 820mm
//		vis.mac: /vis/viewer/set/upThetaPhi 0 90
//						 /vis/viewer/set/viewpointThetaPhi 45 45
//******************************************************************************


#include "cyzDetectorConstruction.hh"

#include "G4RunManager.hh"
#include "G4NistManager.hh"
#include "G4Box.hh"
#include "G4Orb.hh"
#include "G4Sphere.hh"
#include "G4Tubs.hh"
#include "G4SubtractionSolid.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4SystemOfUnits.hh"

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

cyzDetectorConstruction::cyzDetectorConstruction()
: G4VUserDetectorConstruction()
{ }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

cyzDetectorConstruction::~cyzDetectorConstruction()
{ }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4VPhysicalVolume* cyzDetectorConstruction::Construct()
{  
  // Get nist material manager
  G4NistManager* nist = G4NistManager::Instance();
  
  // Option to switch on/off checking of volumes overlaps
  //
  G4bool checkOverlaps = true;

  //     
  // World
  //
  G4double world_size = 5000*mm;  // Human height is almost 1590 mm 
  G4Material* world_mat = nist->FindOrBuildMaterial("G4_AIR");
  
  G4Box* solidWorld =    
    new G4Box("World",                       //its name
       0.5*world_size, 0.5*world_size, 0.5*world_size);     //its size
      
  G4LogicalVolume* logicWorld =                         
    new G4LogicalVolume(solidWorld,          //its solid
                        world_mat,           //its material
                        "World");            //its name
                                   
  G4VPhysicalVolume* physWorld = 
    new G4PVPlacement(0,                     //no rotation
                      G4ThreeVector(),       //at (0,0,0)
                      logicWorld,            //its logical volume
                      "World",               //its name
                      0,                     //its mother  volume
                      false,                 //no boolean operation
                      0,                     //copy number
                      checkOverlaps);        //overlaps checking
                     
  //     
  // Human's head
  //  
  G4double head_diameter = 180*mm;
  G4Material* human_mat = nist->FindOrBuildMaterial("G4_WATER");

  G4Orb* solidHead =    
    new G4Orb("HumanHead",                    //its name
        0.5*head_diameter);                    //its Outer diameter
      
	G4LogicalVolume* logicHead =
    new G4LogicalVolume(solidHead,
                        human_mat,
                        "HumanHead");

  new G4PVPlacement(0,
                    G4ThreeVector(),
                    logicHead,
                    "HumanHead",
                    logicWorld,
                    false,
                    0,
                    checkOverlaps);

	//
	// Human's neck
	//
	G4double neck_dmax = 100*mm;              //Outer diameter
	G4double neck_height = 90*mm;

	G4Tubs* solidNeck = 
		new G4Tubs("HumanNeck",
		           0,                           //Full tube neck, rmin = 0
							 0.5*neck_dmax,
							 0.5*neck_height,
							 0,                           //Phi from 0 to 2*pi, Im NOT SURE if it's OK
							 CLHEP::twopi);

	/********  Boolean Solid: Neck - Head  ********/
	G4double neck_delta_z = -head_diameter*0.5-neck_height*0.3;        //z coordinate of Neck in Head's system
	G4ThreeVector zTrans(0,0,-neck_delta_z); //coordinate of Neck in Head's system
	G4RotationMatrix* Rot = new G4RotationMatrix;                 // No Rotation
	G4VSolid* solidNeckNoHead = 
		new G4SubtractionSolid("HumanNeck-HumanHead",solidNeck,solidHead,Rot,zTrans);

	//
	// Place: NeckNoHead
	//
  G4LogicalVolume* logicNeckNoHead =
    new G4LogicalVolume(solidNeckNoHead,         
                        human_mat,             
                        "HumanNeckNoHead");      

  new G4PVPlacement(0,                         
                    G4ThreeVector(0,0,neck_delta_z),
                    logicNeckNoHead,
                    "HumanNeckNoHead",    
                    logicWorld,   
                    false, 
                    0,                         
                    checkOverlaps);            
	//
	// Human's Body
	//
	G4double body_sizeX = 260*mm;  // Body Length
	G4double body_sizeY = 120*mm;  // Body Weight
	G4double body_sizeZ = 500*mm;  // Body Height
	G4double body_delta_z = neck_delta_z - neck_height*0.5 - body_sizeZ*0.5; // z coordinate of body in World system

  G4Box* solidBody =
    new G4Box("HumanBody",                       //its name
       0.5*body_sizeX, 0.5*body_sizeY, 0.5*body_sizeZ);     //its size

  G4LogicalVolume* logicBody =
    new G4LogicalVolume(solidBody,
                        human_mat,
                        "HumanBody");         

  new G4PVPlacement(0,
                    G4ThreeVector(0,0,body_delta_z),       
                    logicBody,
                    "HumanBody",
                    logicWorld,
                    false,
                    0,
                    checkOverlaps);
	
	//
	// Human's Legs
	//
	G4double leg_dmax = 110*mm;             //Outer diameter
	G4double leg_height = 820*mm;
	G4double leg_delta_z = body_delta_z - 0.5*body_sizeZ - 0.5*leg_height; 
																					//z coordinate of leg in World system
	G4double leg_delta_x = body_sizeX*0.5 - leg_dmax*0.5;
																					//abs of x coordinate of two legs in World system

	G4Tubs* solidLeg =
    new G4Tubs("HumanLeg",
               0,                         //Full tube leg, rmin = 0
               0.5*leg_dmax,
               0.5*leg_height,
               0,                         //Phi from 0 to 2*pi
               CLHEP::twopi);

	G4LogicalVolume* logicLeg = 
			new G4LogicalVolume(solidLeg,
													human_mat,
													"HumanLeg");
	new G4PVPlacement(0,
                    G4ThreeVector(leg_delta_x,0,leg_delta_z),
                    logicLeg,
                    "HumanLeg",
                    logicWorld,
                    false,
                    0,
                    checkOverlaps);
  new G4PVPlacement(0,
                    G4ThreeVector(-leg_delta_x,0,leg_delta_z),
                    logicLeg,
                    "HumanLeg",
                    logicWorld,
                    false,
                    0,
                    checkOverlaps);	

	fScoringHead = logicHead;
	fScoringBody = logicBody;
  return physWorld;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
